﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace katOS
{
    class UserPrograms
    {
        public void Set(Process new_process, String reg_name, String value)
        {
            if(!isRegister(reg_name))
            {
                Console.WriteLine("Invalid register on Set");
            }
            else if(!isRegister(value))
            {
                new_process.setRegister(reg_name, int.Parse(value));
            }
            else
            {
                new_process.setRegister(reg_name, new_process.getRegister(value));
            }
        }

        public void Add(Process new_process, String destiny, String source, String source2)
        {
            if(!isRegister(destiny))
            {
                Console.WriteLine("Invalid register on Add's destiny");
            }
            else if(!isRegister(source))
            {
                Console.WriteLine("Invalid register on Add's source");
            }
            else if(!isRegister(source2))
            {
                Console.WriteLine("Invalid register on Add's source2");
            }
            else
            {
                int a = new_process.getRegister(source);
                int b = new_process.getRegister(source2);
                int sum = a+b;
                new_process.setRegister(destiny,sum);
            }
        }

        public void Sub(Process new_process, String destiny, String source, String source2)
        {
            if (!isRegister(destiny))
            {
                Console.WriteLine("Invalid register on Sub's destiny");
            }
            else if (!isRegister(source))
            {
                Console.WriteLine("Invalid register on Sub's source");
            }
            else if (!isRegister(source2))
            {
                Console.WriteLine("Invalid register on Sub's source2");
            }
            else
            {
                int a = new_process.getRegister(source);
                int b = new_process.getRegister(source2);
                int sub = a - b;
                new_process.setRegister(destiny, sub);
            }
        }

        public void Mul(Process new_process, String destiny, String source, String source2)
        {
            if (!isRegister(destiny))
            {
                Console.WriteLine("Invalid register on Mul's destiny");
            }
            else if (!isRegister(source))
            {
                Console.WriteLine("Invalid register on Mul's source");
            }
            else if (!isRegister(source2))
            {
                Console.WriteLine("Invalid register on Mul's source2");
            }
            else
            {
                int a = new_process.getRegister(source);
                int b = new_process.getRegister(source2);
                int sum = a * b;
                new_process.setRegister(destiny, sum);
            }
        }

        public void Div(Process new_process, String destiny, String dividend, String divisor, String remainder)
        {
            if (!isRegister(destiny))
            {
                Console.WriteLine("Invalid register on Div's destiny");
            }
            else if (!isRegister(dividend))
            {
                Console.WriteLine("Invalid register on Div's source");
            }
            else if (!isRegister(divisor))
            {
                Console.WriteLine("Invalid register on Div's source2");
            }
            else if (!isRegister(remainder))
            {
                Console.WriteLine("Invalid register on Div's remainder");
            }
            else
            {
                int div1 = new_process.getRegister(divisor);
                int div2 = new_process.getRegister(dividend);
                new_process.setRegister(destiny, div1 / div2);
                new_process.setRegister(remainder, div1 % div2);
            }
        }

        public void Echo(Process new_process, string a_string)
        {
            string to_print="";
            if(isRegister(a_string))
            {
                to_print = ""+new_process.getRegister(a_string);
            }
            else if (a_string.StartsWith("\"") && a_string.EndsWith("\"") && a_string.CompareTo("\"\"")!=0)
            {
                to_print = a_string.TrimStart('"');
                to_print = a_string.TrimEnd('"');
            }
            else
            {
                to_print = "Invalid Echo"; 
            }
            Console.WriteLine(to_print);
        }

        public string getState(Process new_process)
        {
            string state = "";
            int stateid = new_process.getState();

            switch (stateid)
            {
                case 1:
                    return "New";
                case 2:
                    return "Ready";
                case 3:
                    return "Running";
                case 4:
                    return "Waiting";
                case 5:
                    return "Terminated";
            }
            return state;
        }

        public int Jmp(Process new_process, string reg, string tag)
        {
            int ip_to_jump=0;
            string [,] temp_symbols_table = new_process.getSymbolsTable();
            for (int i = 0; i < temp_symbols_table.Length; i++)
            {
                if (temp_symbols_table[i, 0].Equals(tag))
                {
                    int temp_ip = int.Parse(temp_symbols_table[i, 1]);
                    if(!isRegister(reg))
                    {
                        Console.WriteLine("Invalid register on Jmp");
                    }
                    else
                    {
                        if (new_process.getRegister(reg) > 0)
                            ip_to_jump = temp_ip;
                        else
                            ip_to_jump = 0;
                    }
                }
                else
                {
                    Console.WriteLine("Not such tag defined");
                }
            }
            return ip_to_jump;
        }

        public int End(Process new_process, string reg)
        {
            int value = -1;
            if(!isRegister(reg))
            {
                Console.WriteLine("Invalid register on End");
            }
            else
            {
                value = new_process.getProcessValue();
            }
            return value;
        }

        private bool isRegister(string pos_reg)
        {
            pos_reg = pos_reg.ToLower();
            bool reg = false;
            if (pos_reg.Equals("r0") || pos_reg.Equals("r1") || pos_reg.Equals("r2") || pos_reg.Equals("r3") || pos_reg.Equals("r4") || pos_reg.Equals("r5") || pos_reg.Equals("r6") || pos_reg.Equals("r7"))
            {
                reg = true;
            }
            return reg;
        }
    }
}
